package com.thwj.project.app.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.thwj.common.exception.ServiceException;
import com.thwj.common.utils.WzDateUtil;
import com.thwj.project.app.event.ActivitySignUpSuccessEvent;
import com.thwj.project.app.event.PaySuccessEvent;
import com.thwj.project.biz.domain.Activity;
import com.thwj.project.biz.domain.ActivitySignup;
import com.thwj.project.biz.domain.User;
import com.thwj.project.biz.domain.UserVip;
import com.thwj.project.biz.enums.AccountInoutStatusEnum;
import com.thwj.project.biz.enums.AccountSourceTypeEnum;
import com.thwj.project.biz.enums.ActivitySignUpStatusEnum;
import com.thwj.project.biz.enums.UserVipStatusEnum;
import com.thwj.project.biz.service.IActivityService;
import com.thwj.project.biz.service.IActivitySignupService;
import com.thwj.project.biz.service.IUserService;
import com.thwj.project.biz.service.IUserVipService;
import com.thwj.project.pay.domain.WxPay;
import com.thwj.project.pay.enums.OrderSourceTypeEnum;
import com.thwj.project.pay.enums.PayStatusEnum;
import com.thwj.project.pay.service.IWxCallbackInfoService;
import com.thwj.project.pay.service.IWxPayService;
import com.thwj.project.pay.service.IWxRefundCallbackInfoService;
import com.thwj.project.pay.service.IWxRefundInfoService;
import com.thwj.project.push.MpPushMessageService;
import com.thwj.project.push.enums.PushTemplateEnumNew;
import com.thwj.project.push.event.WxMpMessageEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

@Slf4j
@Transactional
@Service
public class Trade2OrderService {

    @Autowired
    IActivitySignupService activitySignupService;
    @Autowired
    IUserVipService userVipService;
    @Autowired
    IWxCallbackInfoService wxCallbackInfoService;
    @Autowired
    IWxRefundInfoService wxRefundInfoService;
    @Autowired
    IWxRefundCallbackInfoService wxRefundCallbackInfoService;
    @Autowired
    IWxPayService wxPayService;
    @Autowired
    IActivityService activityService;
    @Autowired
    AppAccountService appAccountService;
    @Autowired
    ApplicationEventPublisher applicationEventPublisher;
    @Autowired
    IUserService userService;
    @Autowired
    MpPushMessageService mpPushMessageService;


    @Async
    @EventListener
    @Retryable(value = Exception.class)
    public void onWxPaySuccessEvent(PaySuccessEvent event) {

        WxPay wxPay = wxPayService.getById(event.getCallbackWxPay().getId());
        // 更新支付状态
        wxPay.setStatus(PayStatusEnum.PAID.getValue());
        wxPay.setPayMoney(wxPay.getActualMoney());
        wxPay.setPaySuccessDate(new Date());
        wxPay.setOutTradeNo(event.getCallbackWxPay().getOutTradeNo());
        if(!wxPayService.updateById(wxPay)){
            log.error("微信支付回调处理业务更新数据为空 event :{}", event);
            throw new ServiceException("微信支付回调处理业务更新数据为空");
        }

        // 这里需要更新对应的业务逻辑 这里偷懒使用了 订单号 首字母作为区分订单来源的方案
        if (wxPay.getOrderNumber().startsWith(OrderSourceTypeEnum.activity_sign_up.getOrderPrefix())) {
            // 处理报名相关页面逻辑
            ActivitySignup activitySignup = activitySignupService.getById(wxPay.getSourceId());
            if (activitySignup == null) {
                log.error("微信支付回调 金额不一致 PaySuccessEvent:{}, WxPay:{},activitySignup:{}", event, wxPay, activitySignup);
                throw new ServiceException("没有找到 报名信息");
            }
            activitySignupService.update(
                    new UpdateWrapper<ActivitySignup>()
                            .set("status", ActivitySignUpStatusEnum.sign_up_ed.getValue())
                            .set("pay_date", wxPay.getPaySuccessDate())
                            .set("order_number", wxPay.getOrderNumber())
                            .eq("id", wxPay.getSourceId())
            );
            // 更新活动报名数量
            activityService.update(
                    new UpdateWrapper<Activity>()
                            .setSql("sign_up_count = sign_up_count + 1")
                            .eq("id", activitySignup.getActivityId())
            );
            User user = userService.getById(activitySignup.getUserId());
            Activity activity = activityService.getById(activitySignup.getActivityId());
            // 插入账户记录表
            appAccountService.saveUpdateAccountInout(
                    activity.getUserId(),
                    AccountSourceTypeEnum.activity_sign_up_fee,
                    activitySignup.getId(),
                    user.getUserNickName() + "报名" + activity.getTitle(),
                    activitySignup.getActualMoney(),
                    AccountInoutStatusEnum.auditing
            );
            applicationEventPublisher.publishEvent(
                    ActivitySignUpSuccessEvent.builder()
                            .activity(activity)
                            .signup(activitySignup)
                            .build());


            applicationEventPublisher.publishEvent(WxMpMessageEvent.builder()
                    .userId(activity.getUserId())
                    .pushTemplateEnum(PushTemplateEnumNew.ACTIVITY_MONEY_ARRIVAL)
                    .miniAppPath("pages/detail/detail?activityId="+ activity.getId())
                    .templateDataList(PushTemplateEnumNew.ACTIVITY_MONEY_ARRIVAL(
                                    activity.getTitle(),
                                    user.getUserNickName(),
                                    activity.getLocationName(),
                                    activitySignup.getActualMoney().toPlainString(),
                                    WzDateUtil.date2String(activity.getStartDate(),WzDateUtil.TIME_FORMAT_A)))
                            .build()
            );

        }

        if (wxPay.getOrderNumber().startsWith(OrderSourceTypeEnum.VIP_ORDER.getOrderPrefix())) {
            // 处理报名相关页面逻辑
            // 处理报名相关页面逻辑
            UserVip userVip = userVipService.getOne(new QueryWrapper<UserVip>()
                    .eq("order_number",wxPay.getOrderNumber())
                    .orderByDesc("create_date"),false);
            if (userVip == null) {
                log.error("微信支付回到没有找到原始的vip订单 PaySuccessEvent:{}, WxPay:{},activitySignup:{}", event, wxPay, userVip);
                throw new ServiceException("没有找到 vip订单信息");
            }
            userVipService.update(
                    new UpdateWrapper<UserVip>()
                            .set("status", UserVipStatusEnum.working.getValue())
                            .set("pay_date", wxPay.getPaySuccessDate())
                            .set("vip_start_date", wxPay.getPaySuccessDate())
                            .eq("id", wxPay.getSourceId())
            );
        }
    }

    @Recover
    public int recover(Exception e, int code){
        System.out.println("回调方法执行！！！！");
        //记日志到数据库 或者调用其余的方法
        System.out.println("异常信息:"+e.getMessage());
        return 400;
    }
}
